<template>
    <div class="flex flex-1 flex-col overflow-hidden">
        <div class="flex h-full overflow-hidden">
            <!-- 左侧 -->
            <div :class="fileLists.length <= 0 ? 'w-full' : 'min-w-[540px] border-r border-br-extra-light'">
                <el-scrollbar>
                    <div class="p-4">
                        <!-- 上传组件 -->
                        <div class="mb-4">
                            <el-upload
                                v-model:file-list="fileLists"
                                :headers="uploadParams.headers"
                                :action="uploadParams.action"
                                :data="uploadParams.data"
                                :accept="uploadParams.accept"
                                :limit="15"
                                :multiple="true"
                                :show-file-list="false"
                                :on-success="uploadSuccess"
                                drag
                            >
                                <div class="flex flex-col items-center mb-1">
                                    <icon name="svg-icon-Upload" :size="46" color="var(--el-text-color-placeholder)" />
                                    <span class="pt-2 text-base text-tx-regular">
                                        <el-button type="primary" link>点击上传</el-button> 或 拖拽文档到这里
                                    </span>
                                </div>
                                <div class="text-sm text-tx-secondary">支持 .txt, .docx, .pdf, .md, .html, .pptx 类型文件</div>
                                <div class="text-sm text-tx-secondary">最多支持 15 个文件 单个文件最大 30 MB</div>
                            </el-upload>
                        </div>

                        <!-- 规则配置 -->
                        <div v-if="fileLists.length > 0" class="segment-type-box">
                            <h5 class="mb-2 text-base text-tx-regular">训练模式:</h5>
                            <div class="flex items-center">
                                <div class="segment mr-4" @click="formData.train_mode === 'chunk'">
                                    <el-radio v-model="formData.train_mode" value="chunk" size="large">
                                        <div class="flex items-center">
                                            <span class="mr-2">直接分段</span>
                                            <el-popover
                                                placement="bottom"
                                                effect="dark"
                                                trigger="hover"
                                                :width="300"
                                                content="将文本按规则分段处理后，将段落内容转换为支持语义检索的格式，适合大多数场景。"
                                            >
                                                <template #reference>
                                                    <icon name="svg-icon-Question" />
                                                </template>
                                            </el-popover>
                                        </div>
                                    </el-radio>
                                </div>
                                <div class="segment" @click="formData.train_mode === 'qa'">
                                    <el-radio v-model="formData.train_mode" value="qa" size="large">
                                        <div class="flex items-center">
                                            <span class="mr-2">问答拆分</span>
                                            <el-popover
                                                placement="bottom"
                                                effect="dark"
                                                trigger="hover"
                                                :width="300"
                                                content="基于规则的分段策略，将原始文本划分为较大段落单元，
                                                并调用AI为每个段落生成精准的问答对。这种方法在确保高检索精度的同时，
                                                会不可避免地损失部分文本细节信息。"
                                            >
                                                <template #reference>
                                                    <icon name="svg-icon-Question" />
                                                </template>
                                            </el-popover>
                                        </div>
                                    </el-radio>
                                </div>
                            </div>

                            <h5 class="mt-4 mb-2 text-base text-tx-regular">处理方式:</h5>
                            <div class="grid gap-3">
                                <div
                                    class="segment"
                                    :class="formData.chunk_type === 'automatic' ? 'active' : ''"
                                    @click="formData.chunk_type = 'automatic'"
                                >
                                    <el-radio v-model="formData.chunk_type" value="automatic" size="large">自动</el-radio>
                                    <p class="ml-5 text-xs text-tx-placeholder">自动设置分割和预处理规则</p>
                                </div>
                                <div
                                    class="segment"
                                    :class="formData.chunk_type === 'custom' ? 'active' : ''"
                                    @click="formData.chunk_type = 'custom'"
                                >
                                    <el-radio v-model="formData.chunk_type" value="custom" size="large">自定义规则</el-radio>
                                    <p class="ml-5 text-xs text-tx-placeholder">自定义设置分制和预处理规则</p>
                                    <div v-if="formData.chunk_type === 'custom'" class="ml-5 mt-4">
                                        <p class="mb-1 text-tx-regular">切割分块长度</p>
                                        <el-input
                                            v-model="formData.chunk_size"
                                            type="number"
                                            :min="chunk_size_range[formData.train_mode]['min']"
                                            :max="chunk_size_range[formData.train_mode]['max']"
                                        />
                                    </div>
                                    <div v-if="formData.chunk_type === 'custom'" class="ml-5 mt-4">
                                        <p class="mb-1 text-tx-regular">切割重叠字符</p>
                                        <el-input v-model="formData.chunk_overlap" type="number" :min="0" :max="1000" />
                                    </div>
                                    <div v-if="formData.chunk_type === 'custom'" class="ml-5 mt-4">
                                        <p class="mb-1 text-tx-regular">自定义分隔符</p>
                                        <el-input v-model="formData.separators" placeholder="==SPLIT=="/>
                                    </div>
                                </div>
                            </div>
                        </div>

                        <!-- 文件列表 -->
                        <ul v-if="fileLists.length > 0" class="file-list-box">
                            <li
                                v-for="(item, index) in fileLists"
                                :key="index"
                                :class="index === fileIndex ? 'active' : ''"
                                @click="handleChange(index)"
                            >
                                <el-image
                                    class="w-[24px] h-[24px] mr-2"
                                    :src="suffixUtil.findUnitIcon(item.name)"
                                />
                                <div class="flex-1">
                                    <h3>{{ item.name }}</h3>
                                    <div v-if="parseInt(String(item.percentage)) < 100" class="h-[18px] pr-10">
                                        <el-progress
                                            :percentage="item.percentage"
                                            :stroke-width="6"
                                            :duration="10"
                                            striped-flow
                                            striped
                                        />
                                    </div>
                                    <div v-else class="ml-1 text-xs text-tx-placeholder">
                                        {{ toolsUtil.formatBytes(item.size||0) }}
                                    </div>
                                </div>
                                <icon name="el-icon-Delete" :size="16" @click.stop="deleteFile(index)" />
                            </li>
                        </ul>
                    </div>
                </el-scrollbar>
            </div>

            <!-- 右侧 -->
            <div v-if="fileLists.length > 0" class="flex flex-col flex-1 overflow-hidden">
                <div class="p-4 text-base font-medium text-tx-regular">
                    分段预览 ({{ fileParse.split_count || 0 }})
                    <span
                        v-if="fileParse.split_count >= 20"
                        class="ml-2 text-xs font-normal text-tx-placeholder"
                    >
                        预览最多显示20条
                    </span>
                </div>
                <div v-loading="previewLoading" class="flex-1 overflow-hidden">
                    <el-scrollbar>
                        <div class="parse-list-box">
                            <div v-for="(item, index) in fileParse.lists" :key="index" class="parse-box">
                                <div class="title">
                                    <span class="section">#{{ index + 1 }}</span>
                                    <span class="m-2.5 font-medium text-tx-regular">
                                        {{ fileLists[fileIndex].name }}
                                    </span>
                                </div>
                                <div class="content">{{ item.question }}</div>
                            </div>
                        </div>
                    </el-scrollbar>
                </div>
            </div>
        </div>

        <div
            v-if="fileLists.length > 0"
            class="p-4 pb-2 flex items-center justify-end border-t border-br-extra-light"
        >
            <el-button
                class="ml-3 h-[38px]"
                :disabled="fileLists.length <= 0 || loading || previewLoading"
                @click="resetPreview(fileIndex)"
            >重新预览</el-button>
            <el-button
                class="ml-3 h-[38px]"
                type="primary"
                :disabled="fileLists.length <= 0 || previewLoading"
                :loading="loading"
                @click="handleSubmit"
            >确定导入</el-button>
        </div>
    </div>
</template>

<script setup lang="ts">
import type { UploadUserFile } from 'element-plus'
import config from '~/config/index'
import feedback from '~/utils/feedback'
import toolsUtil from '~/utils/tools'
import suffixUtil from '~/utils/suffix'
import useUserStore from '~/stores/user'
import knowArchiveApi from '~/api/agent/know/archive'

const emits = defineEmits(['retreat'])
const props = defineProps({
    kb: {
        type: String,
        default: ''
    }
})

// 预览加载
const previewLoading = ref<boolean>(false)

// 切割大小
const chunk_size_range: any = {
    chunk: {default: 512, min: 100, max: 8000},
    qa: {default: 8000, min: 3000, max: 32000}
}

// 上传参数
const uploadParams = ref({
    action: config.baseUrl + config.urlPrefix + '/upload/kb',
    accept: '.doc,.docx,.ppt,.pptx,.pdf,.md,.txt,.html,.xlsx',
    headers: {
        Authorization: 'Bearer ' + useUserStore().token,
        Terminal: config.terminal
    },
    data: {
        scene: 'raw'
    }
})

// 文件数据
const fileIndex = ref<number>(-1)
const fileLists = ref<UploadUserFile[]>([])
const fileParse = ref({} as KnowArchiveParseResponse)

// 表单数据
const loading = ref<boolean>(false)
const formData = reactive({
    kb: props.kb,
    scene: 'file',
    train_mode: 'chunk',
    chunk_type: 'automatic',
    chunk_size: 512,
    chunk_overlap: 0,
    separators: '',
    files: []
})

/**
 * 上传成功处理
 *
 * @param response
 * @param file
 * @author zero
 */
const uploadSuccess = (response: any, file: any) => {
    if (response.code === 0) {
        const index = fileLists.value.indexOf(file)
        fileLists.value[index].url = response.data.url
        if (fileIndex.value <= -1 && fileLists.value.length > 0) {
            fileIndex.value = 0
        } else if (fileLists.value.length > 0) {
            fileIndex.value = fileLists.value.length - 1
        }
    } else {
        fileLists.value.pop()
        feedback.msgError(response.msg)
    }
}

/**
 * 重新预览
 */
const resetPreview = async (index: number) => {
    previewLoading.value = true
    const fileUrl = fileLists.value[index].url
    fileParse.value = await knowArchiveApi.parse({
        kb: formData.kb,
        scene: formData.scene,
        chunk_size: formData.chunk_size,
        separators: formData.separators,
        chunk_overlap: formData.chunk_overlap,
        url: String(fileUrl)
    }).finally(() => {
        setTimeout(() => {
            previewLoading.value = false
        }, 500)
    })
}

/**
 * 文件删除
 */
const deleteFile = (index: number) => {
    fileLists.value.splice(index, 1)
    if (fileLists.value.length <= 0) {
        fileIndex.value = -1
        fileParse.value = {} as KnowArchiveParseResponse
    } else {
        fileIndex.value = 0
    }
}

/**
 * 文件切换
 *
 * @param {number} index
 * @author zero
 */
const handleChange = (index: number) => {
    const file = fileLists.value[index]
    const percentage = parseInt(String(file.percentage))
    if (fileIndex.value === index) {
        return
    } else if (percentage < 100 || !file.url) {
        return feedback.msgError('请耐心等待上传完毕')
    }

    fileIndex.value = index
}

/**
 * 提交导入
 */
const handleSubmit = async () => {
    loading.value = true
    await knowArchiveApi.imports({
        kb: formData.kb,
        scene: formData.scene,
        train_mode: formData.train_mode,
        chunk_size: formData.chunk_size,
        chunk_overlap: formData.chunk_overlap,
        separators: formData.separators,
        files: fileLists.value
    }).finally(() => {
        loading.value = false
    })

    feedback.msgSuccess('导入成功')
    emits('retreat')
}

watch(
    () => fileIndex.value,
    async (index: number) => {
        await resetPreview(index)
    }
)

watch(
    () => formData.train_mode,
    (val) => {
        formData.chunk_size = chunk_size_range[val].default
    }, {
        immediate: true
    }
)
</script>

<style scoped lang="scss">
.segment-type-box {
    padding: 12px;
    background-color: var(--el-color-light);
    border: 1px dashed var(--el-border-color-light);
    border-radius: 6px;
    .segment {
        padding: 10px 12px;
        cursor: pointer;
        background-color: var(--color-white);
        border: 1px solid var(--el-border-color-lighter);
        border-radius: 8px;
        :deep(.el-radio.el-radio--large) {
            height: auto;
            .el-radio__label {
                color: var(--el-text-color-regular);
            }
        }
    }
}

.parse-list-box {
    .parse-box {
        box-sizing: border-box;
        margin: 0 16px 12px;
        border: 1px solid var(--el-border-color-lighter);
        border-radius: 6px;
        .title {
            padding: 10px;
            font-size: 15px;
            font-weight: 700;
            border-bottom: 1px solid var(--el-border-color-lighter);
            .section {
                padding: 2px 10px;
                font-size: 13px;
                color: var(--el-color-primary);
                background-color: var(--el-bg-color-page);
                border-radius: 4px;
            }
        }
        .content {
            padding: 8px 15px;
            background-color: var(--el-bg-color-page);
        }
    }
}

.file-list-box {
    margin-top: 15px;
    li {
        display: flex;
        align-items: center;
        width: 100%;
        padding: 8px 14px;
        margin-bottom: 12px;
        cursor: pointer;
        border: 1px solid var(--el-border-color-light);
        border-radius: 8px;
        &.active {
            border-color: var(--el-color-primary);
        }
        .el-icon:hover {
            color: var(--el-color-error);
        }
        h3 {
            margin: 0 4px;
            font-size: 14px;
            color: var(--el-text-color-regular);
        }
    }
}
</style>
